package data

import (
	"context"
	"fmt"
	"kra/cmd/gorm/dal/model"

	"github.com/go-kratos/kratos/v2/log"
)

type UserUseCase struct {
	data *Data
	log  *log.Helper
}

func NewAppUseCase(data *Data, logger log.Logger) *UserUseCase {
	return &UserUseCase{
		data: data,
		log:  log.NewHelper(logger),
	}
}

func (a *UserUseCase) Create(ctx context.Context) {
	var err error
	q := a.data.Q
	ud := q.User.WithContext(ctx)

	userData := &model.User{ID: 1, Name: "modi"}
	// INSERT INTO `users` (`created_at`,`updated_at`,`deleted_at`,`name`,`age`,`role`,`id`) VALUES ('2021-09-13 20:05:51.389','2021-09-13 20:05:51.389',NULL,'modi',0,'',1)
	err = ud.Create(userData)
	fmt.Println(err)

	userDataArray := []*model.User{{ID: 2, Name: "A"}, {ID: 3, Name: "B"}}
	err = ud.CreateInBatches(userDataArray, 2)
	fmt.Println(err)
	// INSERT INTO `users` (`created_at`,`updated_at`,`deleted_at`,`name`,`age`,`role`,`id`) VALUES ('2021-09-13 20:05:51.403','2021-09-13 20:05:51.403',NULL,'A',0,'',2),('2021-09-13 20:05:51.403','2021-09-13 20:05:51.403',NULL,'B',0,'',3)

	userData.Name = "new name"
	err = ud.Save(userData)
	fmt.Println(err)
	// INSERT INTO `users` (`created_at`,`updated_at`,`deleted_at`,`name`,`age`,`role`,`id`) VALUES ('2021-09-13 20:05:51.389','2021-09-13 20:05:51.409',NULL,'new name',0,'',1) ON DUPLICATE KEY UPDATE `updated_at`=VALUES(`updated_at`),`deleted_at`=VALUES(`deleted_at`),`name`=VALUES(`name`),`age`=VALUES(`age`),`role`=VALUES(`role`)
}

func (a *UserUseCase) Delete(ctx context.Context) {
	var err error

	q := a.data.Q
	u, ud := q.User, q.User.WithContext(ctx)

	_, err = ud.Where(u.ID.Eq(1)).Delete()
	fmt.Println(err)
	// UPDATE `users` SET `deleted_at`='2021-09-13 20:05:51.418' WHERE `users`.`id` = 1 AND `users`.`deleted_at` IS NULL

	_, err = ud.Where(u.ID.In(2, 3)).Delete()
	fmt.Println(err)
	// UPDATE `users` SET `deleted_at`='2021-09-13 20:05:51.428' WHERE `users`.`id` IN (2,3) AND `users`.`deleted_at` IS NULL

	_, err = ud.Where(u.ID.Gt(100)).Unscoped().Delete()
	fmt.Println(err)
	// DELETE FROM `users` WHERE `users`.`id` > 100
}

func (a *UserUseCase) Query(ctx context.Context) {
	var err error
	var user *model.User
	var users []*model.User

	q := a.data.Q
	u, ud := q.User, q.User.WithContext(ctx)

	/*--------------Basic query-------------*/
	user, err = ud.Take()
	// SELECT * FROM `users` WHERE `users`.`deleted_at` IS NULL LIMIT 1
	fmt.Printf("query 1 item: %+v", user)
	if err != nil {
		fmt.Println(err)
	}

	user, err = ud.Where(u.ID.Gt(100), u.Name.Like("%T%")).Take()
	// SELECT * FROM `users` WHERE `users`.`id` > 100 AND `users`.`name` LIKE '%T%' AND `users`.`deleted_at` IS NULL LIMIT 1
	fmt.Printf("query conditions got: %+v", user)

	user, err = ud.Where(ud.Columns(u.ID).In(ud.Select(u.ID.Min()))).First()
	// SELECT * FROM `users` WHERE `users`.`id` IN (SELECT MIN(`users`.`id`) FROM `users` WHERE `users`.`deleted_at` IS NULL) AND `users`.`deleted_at` IS NULL
	// ORDER BY `users`.`id` LIMIT 1
	fmt.Printf("subquery 1 got item: %+v", user)

	user, err = ud.Where(ud.Columns(u.ID).Eq(ud.Select(u.ID.Max()))).First()
	// SELECT * FROM `users` WHERE `users`.`id` = (SELECT MAX(`users`.`id`) FROM `users` WHERE `users`.`deleted_at` IS NULL) AND `users`.`deleted_at` IS NULL
	// ORDER BY `users`.`id` LIMIT 1
	fmt.Printf("subquery 2 got item: %+v", user)

	users, err = ud.Distinct(u.Name).Find()
	// SELECT DISTINCT `users`.`name` FROM `users` WHERE `users`.`deleted_at` IS NULL
	fmt.Printf("select distinct got: %d", len(users))

	/*--------------Diy query-------------*/
	// user, err = ud.FindByNameAndAge("tom", 29)
	// fmt.Println(err)
	// // SELECT * FROM `users` WHERE name='tom' and age=29 AND `users`.`deleted_at` IS NULL
	// fmt.Printf("FindByNameAndAge: %+v", user)
}
